using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Caching.Memory;
using Lzfy_Refund_Service.Models;

namespace Lzfy_Refund_Service.Services
{

    /// <summary>
    /// 企业微信服务实现
    /// </summary>
    public class WeChatService : IWeChatService
    {
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _configuration;
        private readonly ILogger<WeChatService> _logger;
        private readonly IMemoryCache _cache;

        private string CorpId => _configuration["WeChat:CorpId"] ?? "";
        private string CorpSecret => _configuration["WeChat:CorpSecret"] ?? "";
        private string AgentId => _configuration["WeChat:AgentId"] ?? "";
        private string Token => _configuration["WeChat:Token"] ?? "";

        public WeChatService(
            HttpClient httpClient,
            IConfiguration configuration,
            ILogger<WeChatService> logger,
            IMemoryCache cache)
        {
            _httpClient = httpClient;
            _configuration = configuration;
            _logger = logger;
            _cache = cache;
        }

        /// <summary>
        /// 获取企业微信Access Token
        /// </summary>
        public async Task<string> GetAccessTokenAsync()
        {
            const string cacheKey = "wechat_access_token";
            
            if (_cache.TryGetValue(cacheKey, out string? cachedToken) && !string.IsNullOrEmpty(cachedToken))
            {
                return cachedToken;
            }

            try
            {
                var url = $"https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={CorpId}&corpsecret={CorpSecret}";
                var response = await _httpClient.GetStringAsync(url);
                var tokenResponse = JsonSerializer.Deserialize<WeChatAccessTokenResponse>(response);

                if (tokenResponse?.ErrCode == 0 && !string.IsNullOrEmpty(tokenResponse.AccessToken))
                {
                    // 缓存token，提前5分钟过期
                    var expiry = TimeSpan.FromSeconds(tokenResponse.ExpiresIn - 300);
                    _cache.Set(cacheKey, tokenResponse.AccessToken, expiry);
                    
                    return tokenResponse.AccessToken;
                }

                _logger.LogError("获取企业微信Access Token失败: {ErrorCode} - {ErrorMessage}", 
                    tokenResponse?.ErrCode, tokenResponse?.ErrMsg);
                return string.Empty;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取企业微信Access Token异常");
                return string.Empty;
            }
        }

        /// <summary>
        /// 根据授权码获取用户信息
        /// </summary>
        public async Task<WeChatUserInfo> GetUserInfoByCodeAsync(string code)
        {
            try
            {
                var accessToken = await GetAccessTokenAsync();
                if (string.IsNullOrEmpty(accessToken))
                {
                    throw new Exception("无法获取企业微信Access Token");
                }

                // 1. 根据code获取用户身份
                var getUserUrl = $"https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token={accessToken}&code={code}";
                var getUserResponse = await _httpClient.GetStringAsync(getUserUrl);
                var userResponse = JsonSerializer.Deserialize<WeChatGetUserResponse>(getUserResponse);

                if (userResponse?.ErrCode != 0 || string.IsNullOrEmpty(userResponse.UserId))
                {
                    _logger.LogError("获取企业微信用户身份失败: {ErrorCode} - {ErrorMessage}", 
                        userResponse?.ErrCode, userResponse?.ErrMsg);
                    throw new Exception($"获取企业微信用户身份失败: {userResponse?.ErrCode} - {userResponse?.ErrMsg}");
                }

                // 2. 根据用户ID获取用户详细信息
                var getUserDetailUrl = $"https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={accessToken}&userid={userResponse.UserId}";
                var getUserDetailResponse = await _httpClient.GetStringAsync(getUserDetailUrl);
                var userDetailResponse = JsonSerializer.Deserialize<WeChatUserDetailResponse>(getUserDetailResponse);

                if (userDetailResponse?.ErrCode != 0)
                {
                    _logger.LogError("获取企业微信用户详情失败: {ErrorCode} - {ErrorMessage}", 
                        userDetailResponse?.ErrCode, userDetailResponse?.ErrMsg);
                    throw new Exception($"获取企业微信用户详情失败: {userDetailResponse?.ErrCode} - {userDetailResponse?.ErrMsg}");
                }

                return new WeChatUserInfo
                {
                    UserId = userDetailResponse.UserId,
                    Name = userDetailResponse.Name,
                    Department = userDetailResponse.Department,
                    Position = userDetailResponse.Position,
                    Mobile = userDetailResponse.Mobile,
                    Email = userDetailResponse.Email,
                    Avatar = userDetailResponse.Avatar
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取企业微信用户信息异常");
                throw;
            }
        }

        /// <summary>
        /// 生成JS-SDK配置
        /// </summary>
        public async Task<WeChatJsApiConfig> GetJsApiConfigAsync(string url)
        {
            try
            {
                var accessToken = await GetAccessTokenAsync();
                if (string.IsNullOrEmpty(accessToken))
                {
                    throw new Exception("无法获取Access Token");
                }

                // 获取jsapi_ticket
                var ticketUrl = $"https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token={accessToken}";
                var ticketResponse = await _httpClient.GetStringAsync(ticketUrl);
                var ticketData = JsonSerializer.Deserialize<JsonElement>(ticketResponse);

                if (!ticketData.TryGetProperty("errcode", out var errCode) || errCode.GetInt32() != 0)
                {
                    throw new Exception($"获取jsapi_ticket失败: {ticketData}");
                }

                var ticket = ticketData.GetProperty("ticket").GetString() ?? "";
                var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                var nonceStr = Guid.NewGuid().ToString("N")[..16];

                // 生成签名
                var signature = GenerateSignature(ticket, nonceStr, timestamp, url);

                return new WeChatJsApiConfig
                {
                    CorpId = CorpId,
                    AgentId = AgentId,
                    Timestamp = timestamp,
                    NonceStr = nonceStr,
                    Signature = signature,
                    JsApiList = new List<string>
                    {
                        "selectEnterpriseContact",
                        "openEnterpriseChat",
                        "launchMiniProgram",
                        "shareToExternalContact",
                        "shareToExternalMoments",
                        "getCurExternalContact",
                        "getCurExternalChat",
                        "navigateToAddCustomer",
                        "shareAppMessage",
                        "shareWechatMessage",
                        "selectExternalContact",
                        "openUserProfile",
                        "openExternalUserProfile",
                        "chooseImage",
                        "previewImage",
                        "uploadImage",
                        "downloadImage",
                        "getLocalImgData",
                        "startRecord",
                        "stopRecord",
                        "onVoiceRecordEnd",
                        "playVoice",
                        "pauseVoice",
                        "stopVoice",
                        "onVoicePlayEnd",
                        "uploadVoice",
                        "downloadVoice",
                        "translateVoice",
                        "getNetworkType",
                        "openLocation",
                        "getLocation",
                        "hideOptionMenu",
                        "showOptionMenu",
                        "hideMenuItems",
                        "showMenuItems",
                        "hideAllNonBaseMenuItem",
                        "showAllNonBaseMenuItem",
                        "closeWindow",
                        "scanQRCode",
                        "chooseWXPay",
                        "openProductSpecificView",
                        "addCard",
                        "chooseCard",
                        "openCard"
                    }
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "生成JS-SDK配置异常");
                throw;
            }
        }

        /// <summary>
        /// 验证企业微信签名
        /// </summary>
        public bool VerifySignature(string signature, string timestamp, string nonce, string echostr)
        {
            try
            {
                var array = new[] { Token, timestamp, nonce };
                Array.Sort(array);
                var content = string.Join("", array);
                
                using var sha1 = SHA1.Create();
                var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(content));
                var hashString = Convert.ToHexString(hash).ToLower();
                
                return hashString == signature.ToLower();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "验证企业微信签名异常");
                return false;
            }
        }

        /// <summary>
        /// 生成JS-SDK签名
        /// </summary>
        private static string GenerateSignature(string ticket, string nonceStr, long timestamp, string url)
        {
            var content = $"jsapi_ticket={ticket}&noncestr={nonceStr}&timestamp={timestamp}&url={url}";
            
            using var sha1 = SHA1.Create();
            var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(content));
            return Convert.ToHexString(hash).ToLower();
        }
    }
}